;;; af
;;; Language: R5RS

; Para número pequenos o problema aparece quando os números são menores que a constante usada para o teste de precisão em good-enough?
; '0.001'. Podemos tentar contornar esse problema substituindo esse número por um menor.
; Teste:
;
; constante: 0.001
; > (square (my-sqrt 2e-10))
; 0.000976562633203128
;
; constante: 0.000001
; > (square (my-sqrt 2e-10))
; 9.53807652408537e-07
; 
; > (square (sqrt 2e-10))
; 2e-10
;
; Para números grandes o problema é o tempo de termino do programa é indefido.
;
; constante: 0.001
; > (square (my-sqrt 2e10))
; 20000000000.000004
;
; constante: 0.000001
; > (square (my-sqrt 2e10))
; entra em recursão infinita...?
;
; > (square (sqrt 2e10))
; 20000000000.000004
;

(define (square x) (* x x))

(define (new-if predicate then-clause else-clause)
  (cond (predicate then-clause)
        (else else-clause)))

(define (sqrt-iter guess x)
  (if (good-enough? guess x)
          guess
          (sqrt-iter (improve guess x)
                     x)))

(define (improve guess x)
  (average guess (/ x guess)))

(define (average x y)
  (/ (+ x y) 2))

(define (good-enough? guess x)
  (< (abs (- (square guess) x)) 0.000001))

(define (my-sqrt x)
  (sqrt-iter 1.0 x))

(define (new-good-enough? guess last-guess x)
  (< (/ (abs (- guess last-guess)) guess) 0.001))

(define (new-sqrt-iter guess last-guess x)
  (if (new-good-enough? guess last-guess x)
          guess
          (new-sqrt-iter (improve guess x) guess
                     x)))

(define (new-sqrt x)
  (new-sqrt-iter 1.0 0 x)) 

; > (square (new-sqrt 2e10))
; 20000000000.01054
; > (square (new-sqrt 2e-10))
; 2.000000000001054e-10
;
; Sim, funcionou de forma melhor.
